home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
raytrace
/
rayshade
/
graphtal.lzh
/
Graphtal.Amiga
/
rcString.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-26
|
5KB
|
259 lines
/*
* rcString.C - reference counted string class.
*
* Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
* Igor Metz (metz@iam.unibe.ch)
* University of Berne, Switzerland
* All rights reserved.
*
* This software may be freely copied, modified, and redistributed
* provided that this copyright notice is preserved on all copies.
*
* You may not distribute this software, in whole or in part, as part of
* any commercial product without the express consent of the authors.
*
* There is no warranty or other guarantee of fitness of this software
* for any purpose. It is provided solely "as is".
*
*/
#ifdef AMIGA_GCC
#include "string.h"
#endif
#include <iostream.h>
#include "rcString.h"
#include "Error.h"
//___________________________________________________________ rcStringRep
//
// reference counted rcString representation
class rcStringRep
{
friend class rcString;
public:
rcStringRep(char);
rcStringRep(const char*);
~rcStringRep();
private:
char* str;
int len;
int count;
private:
rcStringRep(_Char_p_*);
void ref();
void deref();
};
inline rcStringRep::rcStringRep(char c) {
str = new char[2]; str[0] = c; str[1] = '\0';
count = len = 1;
}
inline rcStringRep::rcStringRep(const char* s) {
len = strlen(s);
str = new char[len+1];
strcpy(str, s);
count = 1;
}
inline rcStringRep::~rcStringRep() {
delete [] str;
}
inline rcStringRep::rcStringRep(_Char_p_* r) {
str = *r; count = 1; len = strlen(str);
}
inline void rcStringRep::ref() {
count++;
}
inline void rcStringRep::deref() {
if (--count <= 0) delete this;
}
//___________________________________________________________ rcString
// constructors and destructors
rcString::rcString() {
rep = new rcStringRep("");
}
rcString::rcString(char c) {
rep = new rcStringRep(c);
}
rcString::rcString(const char* s) {
rep = new rcStringRep(s);
}
rcString::rcString(const rcString &s) {
s.rep->ref(); rep = s.rep;
}
rcString::rcString(_Char_p_* r) {
rep = new rcStringRep(r);
}
rcString::~rcString() {
rep->deref();
}
// status reports
unsigned rcString::length() const {
return rep->len;
}
int rcString::empty() const {
return rep->len == 0;
}
const char* rcString::chars() const {
return rep->str;
}
rcString::operator const char*() const {
return rep->str;
}
// element extraction and substring
char& rcString::operator[](unsigned i)
{
if (i>=length())
Error(ERR_PANIC, "rcString::operator[] index out of range");
/*
* Copy on write!
*/
if (rep->count > 1) {
rep->deref();
rep = new rcStringRep(rep->str);
}
return rep->str[i];
}
char rcString::operator[](unsigned i) const
{
if (i>=length())
Error(ERR_PANIC, "rcString::operator[] index out of range");
return rep->str[i];
}
rcString rcString::operator()(unsigned i, unsigned j)
{
if (j<i || i>=length() || j>=length())
Error(ERR_PANIC, "rcString::operator() index out of range");
char* buf = new char[j-i+1];
strncpy(buf, rep->str+i, j-i);
buf[j-i] = '\0';
return rcString(&buf);
}
// assignment
const rcString& rcString::operator=(char c)
{
rep->deref();
rep = new rcStringRep(c);
return *this;
}
const rcString& rcString::operator=(const char* s)
{
rep->deref();
rep = new rcStringRep(s);
return *this;
}
const rcString& rcString::operator=(const rcString& s)
{
s.rep->ref();
rep->deref();
rep = s.rep;
return *this;
}
// comparison operators
int rcString::operator==(const rcString& s) const {
return (strcmp(rep->str, s.rep->str) == 0);
}
int rcString::operator==(const char* s) const {
return (strcmp(rep->str, s) == 0);
}
int rcString::operator!=(const rcString& s) const {
return (strcmp(rep->str, s.rep->str) != 0);
}
int rcString::operator!=(const char* s) const {
return (strcmp(rep->str, s) != 0);
}
int rcString::operator<(const rcString& s) const {
return (strcmp(rep->str, s.rep->str) < 0);
}
int rcString::operator<=(const rcString& s) const {
return (strcmp(rep->str, s.rep->str) <= 0);
}
int rcString::operator>(const rcString& s) const {
return (strcmp(rep->str, s.rep->str) > 0);
}
int rcString::operator>=(const rcString& s) const {
return (strcmp(rep->str, s.rep->str) >= 0);
}
// concatenation
rcString operator+(const rcString& x, const char* y)
{
char* buf = new char[x.length() + strlen(y) + 1];
strcpy(buf, x.chars());
strcat(buf, y);
return rcString(&buf); // call the private constructor
}
rcString operator+(const char* x, const rcString& y)
{
char* buf = new char[strlen(x) + y.length() + 1];
strcpy(buf, x);
strcat(buf, y.chars());
return rcString(&buf); // call the private constructor
}
rcString operator+(const rcString& x, const rcString& y)
{
char* buf = new char[x.length() + y.length() + 1];
strcpy(buf, x.chars());
strcat(buf, y.chars());
return rcString(&buf); // call the private constructor
}
// stream operators
ostream& operator<<(ostream& os, const rcString& s)
{
return os << s.chars();
}